package org.hibiscus.jdp.app.coding;

import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;

import java.util.*;

/**
 * Description: Mybatis Plus代码生成器
 *
 * @author 然诺
 * @date 2019/7/15 13:49
 */
public class CodeGenerator {

	private static final String DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";
	private static final String URL = "jdbc:mysql://%s:%s/clyf_pf?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false";
	private static final String AUTHOR = "然诺";
	private static final String PROJECT_PATH = "/Users/l/IdeaProjects/clyf_platform";
	private static final String PROJECT_CODING_PATH = "/src/main/java/com/clyf/pf";
	private static final String ROOT_PACKAGE = "com.clyf.pf";
	private static final String MODULE_NAME_PREFIX = "pf-";
	private static final String TABLE_PREFIX = "pf_";
	private static final String GLOBAL_RET_CLASS =  ROOT_PACKAGE + ".common.data.GlobalRet";
	private static final String SUPER_PAGE_QUERY_CLASS =  ROOT_PACKAGE + ".common.data.PageQuery";

	public static void main(String[] args) {
		String dbHost = System.getenv("DB_HOST");
		String dbPort = System.getenv("DB_PORT");
		String dbUser = System.getenv("DB_USER");
		String dbPwd = System.getenv("DB_PWD");
		execute(dbHost, dbPort, dbUser, dbPwd);
	}

	public static void execute(String dbHost, String dbPort, String dbUser, String dbPwd) {
		String moduleName = scanner("模块名");
		// 全局配置
		GlobalConfig gc = new GlobalConfig();
		gc.setOutputDir(PROJECT_PATH + "/" + moduleName +"/src/main/java");
		gc.setAuthor(AUTHOR);
		gc.setOpen(false);
		gc.setSwagger2(true);
		gc.setBaseColumnList(true);

		// 数据源配置
		DataSourceConfig dsc = new DataSourceConfig();
		dsc.setDriverName(DRIVER_CLASS_NAME);
		dsc.setUrl(String.format(URL, dbHost, dbPort));
		dsc.setUsername(dbUser);
		dsc.setPassword(dbPwd);

		// 包配置
		PackageConfig pc = new PackageConfig();
		pc.setModuleName(moduleName.substring(MODULE_NAME_PREFIX.length()));
		pc.setParent(ROOT_PACKAGE);
		pc.setEntity("infrastructure.repository.po");
		pc.setMapper("infrastructure.repository.mapper");
		pc.setService("application.service");
		pc.setServiceImpl(pc.getService() + ".impl");
		pc.setController("interfaces.controller");

		// 自定义映射配置
		InjectionConfig cfg = new InjectionConfig() {
			@Override
			public void initMap() {
				Map<String, Object> map = new HashMap<>(3);
				map.put("GlobalRet", GLOBAL_RET_CLASS);
				map.put("BasePageQuery", SUPER_PAGE_QUERY_CLASS);
				map.put("dtoPackage", ROOT_PACKAGE + "." + pc.getModuleName() + ".interfaces.dto");
				map.put("rootPackage", ROOT_PACKAGE);
				this.setMap(map);
			}
		};

		// 自定义输出配置, 自定义配置会被优先输出
		List<FileOutConfig> focList = new ArrayList<>();
		// 配置模板引擎
		// 配置自定义输出模板。指定自定义模板路径，注意不要带上.ftl或.vm, 会根据使用的模板引擎自动识别
		final String entityTemplatePath = "/templates/entity.java.vm";
		final String mapperTemplatePath = "/templates/mapper.java.vm";
		final String serviceTemplatePath = "/templates/service.java.vm";
		final String serviceImplTemplatePath = "/templates/serviceImpl.java.vm";
		final String controllerTemplatePath = "/templates/controller.java.vm";
		final String mapperXmlTemplatePath = "/templates/mapper.xml.vm";
		final String pageTemplatePath = "/templates/pageQuery.java.vm";
		final String entityVOTemplatePath = "/templates/entityDTO.java.vm";
		final String entityCreateQueryTemplatePath = "/templates/entityCreateCmd.java.vm";

		String basePath = PROJECT_PATH + "/" + moduleName + PROJECT_CODING_PATH + "/" + pc.getModuleName() + "/" ;
		focList.add(new FileOutConfig(entityTemplatePath) {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return basePath + "infrastructure/repository/po/" + tableInfo.getEntityName() + StringPool.DOT_JAVA;
			}
		});
		focList.add(new FileOutConfig(mapperTemplatePath) {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return basePath + "infrastructure/repository/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_JAVA;
			}
		});
		focList.add(new FileOutConfig(serviceTemplatePath) {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return basePath + "application/service/" + tableInfo.getEntityName() + "Service" + StringPool.DOT_JAVA;
			}
		});
		focList.add(new FileOutConfig(serviceImplTemplatePath) {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return basePath + "application/service/impl/" + tableInfo.getEntityName() + "ServiceImpl" + StringPool.DOT_JAVA;
			}
		});
		focList.add(new FileOutConfig(controllerTemplatePath) {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return basePath + "interfaces/controller/" + tableInfo.getEntityName() + "Controller" + StringPool.DOT_JAVA;
			}
		});
		// mapper.xml输出文件
		focList.add(new FileOutConfig(mapperXmlTemplatePath) {
			@Override
			public String outputFile(TableInfo tableInfo) {
				// 自定义输出文件名，如果Entity设置了前后缀、此处注意xml的名称会跟着发生变化
				return PROJECT_PATH + "/" + moduleName + "/src/main/resources/mappers/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
			}
		});
		String dtoPath = basePath + "/interfaces/dto/";
		// 分页对象输出文件
		focList.add(new FileOutConfig(pageTemplatePath) {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return dtoPath + tableInfo.getEntityName() + "PageQuery" + StringPool.DOT_JAVA;
			}
		});
		// entityDTO对象输出文件
		focList.add(new FileOutConfig(entityVOTemplatePath) {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return dtoPath + tableInfo.getEntityName() + "DTO" + StringPool.DOT_JAVA;
			}
		});
		// entityCreateQuery对象输出文件
		focList.add(new FileOutConfig(entityCreateQueryTemplatePath) {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return dtoPath + tableInfo.getEntityName() + "CreateCmd" + StringPool.DOT_JAVA;
			}
		});
		cfg.setFileOutConfigList(focList);

		// 配置模板
		TemplateConfig templateConfig = new TemplateConfig();
		templateConfig.setXml(null);
		// 配置自定义输出模板。指定自定义模板路径，注意不要带上.ftl或.vm, 会根据使用的模板引擎自动识别
//		templateConfig.setEntity("/templates/entity.java");
//		templateConfig.setMapper("/templates/mapper.java");
		templateConfig.setService(null);
//		templateConfig.setServiceImpl("/templates/serviceImpl.java");
//		templateConfig.setController("/templates/controller.java");

		// 策略配置
		StrategyConfig strategy = new StrategyConfig();
		strategy.setNaming(NamingStrategy.underline_to_camel);
		strategy.setColumnNaming(NamingStrategy.underline_to_camel);
		strategy.setEntityLombokModel(true);
		//strategy.setSuperEntityClass("x.x.x.BaseEntity");
		//strategy.setSuperEntityColumns("id");
//		strategy.setSuperControllerClass(SUPER_CONTROLLER_CLASS);
		strategy.setRestControllerStyle(true);
		strategy.setControllerMappingHyphenStyle(true);
		strategy.setInclude(scanner("表名(多表以英文逗号分割)").split(","));
		strategy.setTablePrefix(TABLE_PREFIX);

		// 代码生成器
		AutoGenerator mpg = new AutoGenerator();
		mpg.setGlobalConfig(gc);
		mpg.setDataSource(dsc);
		mpg.setPackageInfo(pc);
		mpg.setCfg(cfg);
		mpg.setTemplate(templateConfig);
		mpg.setStrategy(strategy);
		mpg.setTemplateEngine(new VelocityTemplateEngine());
		mpg.execute();
	}

	/**
	 * 读取控制台内容
	 */
	private static String scanner(String tip) {
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入" + tip + "：");
		if (scanner.hasNext()) {
			String ipt = scanner.next();
			if (StringUtils.isNotEmpty(ipt)) {
				return ipt;
			}
		}
		throw new MybatisPlusException("请输入正确的" + tip + "！");
	}

}
